#include "HndToRawFiles.h"
#include "HndFToRawFThreadProc.h"
#include "HndFToRawF.h"
#include <windows.h>
#include <process.h>
#include <cstdio>
#include <string>
#include <vector>
#include <shlwapi.h>
using namespace std;

void HndToRawFiles(char* hndDir, char* hndPrefix, char* hndPostfix,
				   char* rawDir, char* rawPrefix, char* rawPostfix,
				   unsigned int startIndex, unsigned int endIndex,
				   int inFixedWidth, int outFixedWidth)
{
	string hndfp, rawfp;
	char indexString[32];

#ifdef MULTI_THREADED
	volatile LONG doneCount = 0;
	
	const uint numFiles = endIndex - startIndex + 1;

	std::vector<HndFToRawFThreadProcParams> params(numFiles);
	std::vector<HANDLE> threads(numFiles);
	std::vector<double> projAngles(numFiles);
#else
	double projAngle;

	FILE* hndFile;
	FILE* rawFile;
	FILE* projAnglesFile = fopen((string(rawDir) + "\\ProjAngles.txt").c_str(), "w");
#endif

	for (uint i = (uint)startIndex; i <= (uint)endIndex; ++i)
	{
		uint fileId = i - startIndex;
		if (inFixedWidth != -1)
			sprintf(indexString, "%0*d", inFixedWidth, i);
		else
			_itoa(i, indexString, 10);

		hndfp = hndDir;
		hndfp += '\\';
		hndfp += hndPrefix;
		hndfp += indexString;
		hndfp += hndPostfix;

		if (GetFileAttributes(hndfp.c_str()) == INVALID_FILE_ATTRIBUTES)
		{
			printf("Error: hnd_file (%s) does not exist.\n", hndfp.c_str());
			return ;
		}

		if (outFixedWidth != inFixedWidth)
		{
			if (outFixedWidth != -1)
				sprintf(indexString, "%0*d", outFixedWidth, i);
			else
				_itoa(i, indexString, 10);
		}

		rawfp = rawDir;
		rawfp += '\\';
		rawfp += rawPrefix;
		rawfp += indexString;
		rawfp += rawPostfix;
#ifdef MULTI_THREADED
		params[fileId].projAngles = &projAngles[0];
		params[fileId].fileId = fileId;

		params[fileId].hndfile = fopen(hndfp.c_str(), "rb");
		if (!params[fileId].hndfile)
			_asm int 3;
		
		params[fileId].rawfile = fopen(rawfp.c_str(), "wb");
		if (!params[fileId].rawfile)
			_asm int 3;

		params[fileId].doneCount = &doneCount;
		threads[fileId] = (HANDLE)_beginthreadex(NULL, 0, &HndFToRawFThreadProc,
			&params[fileId], 0, NULL);

		printf((string(hndPrefix) + indexString + hndPostfix + " -> "
			+ rawPrefix + indexString + rawPostfix + "\n").c_str());
		fflush(stdout);

		uint threadsRunning = (fileId + 1) - doneCount;
		while (threadsRunning >= 40)
		{
			Sleep(10);
			threadsRunning = (fileId + 1) - doneCount;
		}
#else
		hndFile = fopen(hndfp.c_str(), "rb");
		rawFile = fopen(rawfp.c_str(), "wb");

		//setvbuf(hndFile, 0, _IONBF, 0);
		//setvbuf(rawFile, 0, _IONBF, 0);

		fseek(hndFile, 512 - 64, SEEK_SET);
		fread(&projAngle, sizeof(double), 1, hndFile);
		rewind(hndFile);

		fprintf(projAnglesFile, "%f\n", (float)projAngle);

		HndFToRawF(hndFile, rawFile);

		fclose(hndFile);
		fclose(rawFile);

		printf((string(hndPrefix) + indexString + hndPostfix + " -> "
			+ rawPrefix + indexString + rawPostfix + "\n").c_str());
		//fflush(stdout);
#endif
	}

#ifdef MULTI_THREADED
	while (doneCount != numFiles) { Sleep(10); }

	for (uint i = 0; i < threads.size(); ++i)
		CloseHandle(threads[i]);


	FILE* projAnglesFile = fopen((string(rawDir) + "\\ProjAngles.txt").c_str(), "w");

	for (uint i = 0; i < numFiles; ++i)
		fprintf(projAnglesFile, "%f\n", (float)projAngles[i]);
#endif
	
	fclose(projAnglesFile);
}